package pos.Configuration;

import java.awt.Color;
import java.awt.DisplayMode;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.media.j3d.*;
import javax.vecmath.*;
import pos.utils.*;

/**
 *
 * @author plus
 */
public class ConfigMenu extends BranchGroup implements Invokeable, IContainer {

    private static ArrayList<Pickable> subItems;
    private Pickable currentItem;
    private ConfigController myController;
    private static Dock2D dockFullScreen,  dockRes,  dockGFXLevel,  dockDDU,  dockMusicV,  dockSFXV,  dockAutoATO;

    public ConfigMenu(ConfigController myController) {
        this.myController = myController;
        this.setCapability(ALLOW_DETACH);
        if (subItems == null) {
            initObjects();
        }
        this.compile();
    }

    void setMyController(ConfigController myController) {
        this.myController = myController;
    }

    public void invoke(double Step) {
        for (int itemID = 0; itemID < subItems.size(); itemID++) {
            if (subItems.get(itemID) instanceof Invokeable) {
                ((Invokeable) subItems.get(itemID)).invoke(Step);
            }
        }
    }

    public Object doEvent(String eventName, Object Param) {
        if (eventName.equals("SetHotItem")) {
            refreshCurrentItem((Pickable) Param);
            return null;
        }else if(eventName.startsWith("Profile")){
            return myController.doEvent("ProfileSet", eventName.substring(7));
        } 
        else {
            return myController.doEvent(eventName, Param);
        }
    }

    /**
     * 处理键盘事件
     * @param evt 待处理的键盘事件
     */
    public void processKeyEvent(KeyEvent evt) {
        if (evt.getID() == KeyEvent.KEY_RELEASED) {
            switch (evt.getKeyCode()) {
                case KeyEvent.VK_UP:
                    preItem();
                    break;
                case KeyEvent.VK_DOWN:
                    nextItem();
                    break;
                case KeyEvent.VK_ENTER:
                    currentItem.setStatue(Pickable.Action);
                    break;
                default:
                    if (currentItem instanceof IContainer) {
                        ((IContainer) currentItem).processKeyEvent(evt);
                    }
            }
        }
    }

    /**
     * 添加子对象
     * @param item 需添加的子对象
     * @return 当前主菜单实体中的子对象个数
     */
    public int addSubItem(Pickable item) {
        item.setHost(this);
        subItems.add(item);
        this.addChild((TransformGroup) item);
        return subItems.size();
    }

    private void nextItem() {
        int nextItemID = (subItems.indexOf(currentItem) + 1) % subItems.size();
        refreshCurrentItem(subItems.get(nextItemID));
    }

    private void preItem() {
        int nextItemID = (subItems.indexOf(currentItem) - 1);
        if (nextItemID < 0) {
            nextItemID += subItems.size();
        }
        refreshCurrentItem(subItems.get(nextItemID));
    }

    private void refreshCurrentItem(Pickable currentItem) {
        if (this.currentItem.equals(currentItem)) {
            return;    //仅当变化发生时更新
        }
        this.currentItem = currentItem;
        for (int itemID = 0; itemID < subItems.size(); itemID++) {
            if (!subItems.get(itemID).equals(currentItem)) {
                subItems.get(itemID).setStatue(Pickable.Idle);
            } else {
                subItems.get(itemID).setStatue(Pickable.Hot);
            }
        }
        fixCurrentDockItem();
    }

    void fixCurrentDockItem() {
        if (!currentItem.equals(dockFullScreen)) {
            if (this.myController.CurrentProfile.isFullScreen()) {
                dockFullScreen.setCurrentItem(0);
            } else {
                dockFullScreen.setCurrentItem(1);
            }
        }
        if (!currentItem.equals(dockRes)) {
            dockRes.setCurrentItem(this.myController.CurrentProfile.
                    getAvailableModes().indexOf(this.myController.CurrentProfile.getMode()));
        }
        if (!currentItem.equals(dockDDU)) {
            if (this.myController.CurrentProfile.isDDUScreen()) {
                dockDDU.setCurrentItem(0);
            } else {
                dockDDU.setCurrentItem(1);
            }
        }
        if (!currentItem.equals(dockGFXLevel)) {
            dockGFXLevel.setCurrentItem(this.myController.CurrentProfile.getGFXLevel());
        }
    }

    private void initObjects() {
        subItems = new ArrayList<Pickable>();
        TabBar2D tab = new TabBar2D(new Vector3d(0, 0, 0));
        addSubItem(tab);
        addSubItem(new ImageButton2D(
                new Vector3d(0.3, -0.25, -1), 0.18f, 0.05f, "Image.Config.Save",
                new Color3f(0.8f, 0.8f, 0.8f), new Color3f(0.5f, 0.5f, 0.8f),
                new Color3f(0.5f, 0.8f, 0.5f), "Save", false));
        addSubItem(new ImageButton2D(
                new Vector3d(-0.3, -0.25, -1), 0.18f, 0.05f, "Image.Config.Cancel",
                new Color3f(0.3f, 0.3f, 0.3f), new Color3f(0.8f, 0.8f, 0.3f),
                new Color3f(0.8f, 0.3f, 0.3f), "CancelMsg", false));

        tab.addSubTab(new ImageButton2D(
                new Vector3d(0.08, 0.24, -1), 0.10f, 0.05f, makeTabTexture(" 图 像"),
                new Color3f(0.7f, 0.7f, 0.7f), new Color3f(0.8f, 0.8f, 0.8f),
                new Color3f(1f, 1f, 1f), "TabGFX", false));
        tab.addTabBack(getTG(ObjectFactory.createTexturedSurface(
                0.4f, 0.25f,-1,new Color3f(1f, 1f, 1f),
                0f, PathRes.getPath("Image.Config.GFX"), false, false), -0.1f, 0.05f, 0f));
        initGFXtab(tab);

        tab.addSubTab(new ImageButton2D(
                new Vector3d(0.20, 0.24, -1), 0.1f, 0.05f, makeTabTexture(" 音 量"),
                new Color3f(0.7f, 0.7f, 0.7f), new Color3f(0.8f, 0.8f, 0.8f),
                new Color3f(1f, 1f, 1f), "TabSFX", false));
        tab.addTabBack(getTG(ObjectFactory.createTexturedSurface(
                0.18f, 0.12f, -1,new Color3f(1f, 1f, 1f),
                0f, PathRes.getPath("Image.Config.SFX"), false, false), -0.2f, 0.1f, 0f));

        tab.addSubTab(new ImageButton2D(
                new Vector3d(0.32, 0.24, -1), 0.10f, 0.05f, makeTabTexture(" 控 制"),
                new Color3f(0.7f, 0.7f, 0.7f), new Color3f(0.8f, 0.8f, 0.8f),
                new Color3f(1f, 1f, 1f), "TabGame", false));
        tab.addTabBack(getTG(ObjectFactory.createTexturedSurface(
                0.4f, 0.03f, -1,new Color3f(1f, 1f, 1f),
                0f, PathRes.getPath("Image.Config.CTRL"), false, false), -0.10f, 0.15f, 0f));
        tab.changeTab(0);

        currentItem = subItems.get(0);
        currentItem.setStatue(Pickable.Hot);
    }

    private void initGFXtab(TabBar2D tab) {
        /**
         * 全屏选项
         */
        if (myController.CurrentProfile.isFullScreenSupported()) {
            dockFullScreen = new Dock2D(new Vector3d(-0.12, 0.16, -1), 0.08f, 0.08f, 1.5f);
            dockFullScreen.addSubItem(makeTextTexture("是", 64),
                    new Color3f(0.7f, 0.7f, 0.7f), new Color3f(1.0f, 1.0f, 1.0f),
                    new Color3f(0f, 1f, 1f), "ProfileFullScreen@Enable", "");
            dockFullScreen.addSubItem(makeTextTexture("否", 64),
                    new Color3f(0.7f, 0.7f, 0.7f), new Color3f(1f, 1f, 1f),
                    new Color3f(0f, 1f, 1f), "ProfileFullScreen@Disable", "");
            if (myController.CurrentProfile.isFullScreen()) {
                dockFullScreen.setCurrentItem(0);
            } else {
                dockFullScreen.setCurrentItem(1);
            }
            tab.addSubItem(dockFullScreen);
        }
        /**
         * 分辨率选项
         */
        ArrayList<DisplayMode> Res = myController.CurrentProfile.getAvailableModes();
        dockRes = new Dock2D(new Vector3d(-0.165, 0.1, -1), 0.08f, 0.08f, 1.5f);
        for (int ResID = 0; ResID < Res.size(); ResID++) {
            dockRes.addSubItem(makeResTexture(Res.get(ResID), Res.get(Res.size() - 1)),
                    new Color3f(0.7f, 0.7f, 0.7f), new Color3f(1f, 1f, 1f),
                    new Color3f(0f, 1f, 1f),
                    "ProfileRes@" + Res.get(ResID).getWidth() + "x" + Res.get(ResID).getHeight(),
                    Res.get(ResID).getWidth() + "x" + Res.get(ResID).getHeight());
        }
        dockRes.setCurrentItem(Res.indexOf(myController.CurrentProfile.getMode()));
        tab.addSubItem(dockRes);
        /**
         * 画质选项
         */
        dockGFXLevel = new Dock2D(new Vector3d(-0.06, 0.01, -1), 0.2f, 0.07f, 1.5f);

        dockGFXLevel.addSubItem(makeTextTexture("性能优先", 256),
                new Color3f(0.7f, 0.7f, 0.7f), new Color3f(1f, 1f, 1f),
                new Color3f(0f, 1f, 1f), "ProfileGFX@0", "");
        dockGFXLevel.addSubItem(makeTextTexture("自动平衡", 256),
                new Color3f(0.7f, 0.7f, 0.7f), new Color3f(1f, 1f, 1f),
                new Color3f(0f, 1f, 1f), "ProfileGFX@1", "");
        dockGFXLevel.addSubItem(makeTextTexture("画质优先", 256),
                new Color3f(0.7f, 0.7f, 0.7f), new Color3f(1f, 1f, 1f),
                new Color3f(0f, 1f, 1f), "ProfileGFX@2", "");
        dockGFXLevel.setCurrentItem(myController.CurrentProfile.getGFXLevel());
        tab.addSubItem(dockGFXLevel);
        /**
         * DDU选项
         */
            dockDDU = new Dock2D(new Vector3d(-0.12,-0.12, -1), 0.08f, 0.08f, 1.5f);
            dockDDU.addSubItem(makeTextTexture("是", 64),
                    new Color3f(0.7f, 0.7f, 0.7f), new Color3f(1.0f, 1.0f, 1.0f),
                    new Color3f(0f, 1f, 1f), "ProfileDDU@Enable", "");
            dockDDU.addSubItem(makeTextTexture("否", 64),
                    new Color3f(0.7f, 0.7f, 0.7f), new Color3f(1f, 1f, 1f),
                    new Color3f(0f, 1f, 1f), "ProfileDDU@Disable", "");
            if (myController.CurrentProfile.isDDUScreen()) {
                dockDDU.setCurrentItem(0);
            } else {
                dockDDU.setCurrentItem(1);
            }
            tab.addSubItem(dockDDU);
    }

    private Texture2D makeTabTexture(String Title) {
        BufferedImage tabBuffer = new BufferedImage(128, 64, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = (Graphics2D) tabBuffer.getGraphics();
        g2d.setFont(new Font("微软雅黑", Font.PLAIN, 48));
        g2d.setColor(new Color(0, 0, 0, 128));
        g2d.fillRect(0, 0, 128, 64);
        g2d.setColor(new Color(255, 255, 255));
        g2d.drawString(Title, 0, 48);
        ImageComponent2D ic2D = new ImageComponent2D(ImageComponent.FORMAT_RGBA, tabBuffer, true, false);
        Texture2D textureOut = new Texture2D(Texture.BASE_LEVEL, Texture.RGBA, 128, 64);
        textureOut.setImage(0, ic2D);
        return textureOut;
    }

    private Texture2D makeTextTexture(String Title, int width) {
        BufferedImage tabBuffer = new BufferedImage(width, 64, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = (Graphics2D) tabBuffer.getGraphics();
        g2d.setFont(new Font("微软雅黑", Font.PLAIN, 48));
        g2d.setColor(new Color(255, 255, 255));
        g2d.drawString(Title, 0, 48);
        ImageComponent2D ic2D = new ImageComponent2D(ImageComponent.FORMAT_RGBA, tabBuffer, true, false);
        Texture2D textureOut = new Texture2D(Texture.BASE_LEVEL, Texture.RGBA, width, 64);
        textureOut.setImage(0, ic2D);
        return textureOut;
    }

    private Texture2D makeResTexture(DisplayMode currentDM, DisplayMode max) {
        BufferedImage tabBuffer = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
        int w = (int) ((double) currentDM.getWidth() / max.getWidth() * 64d),
              h = (int) ((double) currentDM.getHeight() / max.getWidth() * 64d),
              maxh = (int) ((double) max.getHeight() / max.getWidth() * 64d);
        Graphics2D g2d = (Graphics2D) tabBuffer.getGraphics();
        g2d.setColor(new Color(0, 0, 0, 128));
        g2d.fillRect(0, (64 - maxh) / 2, 64, maxh);
        g2d.setColor(new Color(150, 150, 150, 255));
        g2d.fillRect((64 - w) / 2, (64 - h) / 2, w, h);
        g2d.setColor(new Color(255, 255, 255, 200));
        g2d.fillRect((68 - w) / 2, (68 - h) / 2, w - 4, h - 4);
        ImageComponent2D ic2D = new ImageComponent2D(ImageComponent.FORMAT_RGBA, tabBuffer, true, false);
        Texture2D textureOut = new Texture2D(Texture.BASE_LEVEL, Texture.RGBA, 64, 64);
        textureOut.setImage(0, ic2D);
        return textureOut;
    }

    private static TransformGroup getTG(Node child, float x, float y, float z) {
        Transform3D transRes = new Transform3D();
        transRes.set(new Vector3f(x, y, z));
        TransformGroup TGRes = new TransformGroup(transRes);
        if (child != null) {
            TGRes.addChild(child);
        }
        return TGRes;
    }
}